package com.chinasoftinc.facommon.control.service;

import ohos.agp.utils.TextTool;
import ohos.rpc.IRemoteBroker;
import ohos.rpc.IRemoteObject;
import ohos.rpc.MessageOption;
import ohos.rpc.MessageParcel;
import ohos.rpc.RemoteException;
import ohos.rpc.RemoteObject;
import ohos.utils.zson.ZSONObject;

import com.huawei.ailife.service.kit.AiLifeServiceHelper;
import com.huawei.ailife.service.kit.constants.ConnectResult;

import com.chinasoftinc.facommon.DeviceControlConstants;
import com.chinasoftinc.facommon.FAApplication;
import com.chinasoftinc.facommon.HilinkRegister;
import com.chinasoftinc.facommon.control.DataMap;
import com.chinasoftinc.facommon.control.conversation.HiLinkDataCallback;
import com.chinasoftinc.facommon.control.conversation.HiLinkDeviceHelper;
import com.chinasoftinc.facommon.utils.LogUtil;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * 功能描述
 *
 * @since 2022-01-25
 */
public class HilinkDeviceRemote extends RemoteObject implements IRemoteBroker {
    private static final String TAG = "BleRemoteObj";
    public static final String DEFAULT_IDENTITY = "default";
    private HiLinkDeviceHelper hiLinkDeviceHelper;
    private int connectResult = ConnectResult.SERVICE_UNAVAILABLE;
    private String deviceId;

    private Map<String, IRemoteObject> remoteObjectHandler = new HashMap<>();
    private String lastIdentity = null;

    public HilinkDeviceRemote() {
        super("BleServiceAbility_BleRemoteObj");
    }

    private final HiLinkDataCallback hiLinkDataCallback = new HiLinkDataCallback() {
        @Override
        public void onSuccess(int dataType, String result) {
            sendData(formatData(DeviceControlConstants.STATE_SUCCESS, dataType, result));
        }

        @Override
        public void onFail(int dataType, int code, String result) {
            sendData(formatData(DeviceControlConstants.STATE_FAIL, dataType, result));
        }

        @Override
        public void onBleConnectStateChange(int connectState, String msg) {
            final Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("state", DeviceControlConstants.STATE_SUCCESS);
            dataMap.put("type", DeviceControlConstants.DATA_TYPE_BLE_CONNECTION_STATE_CHANGED);
            dataMap.put("connectState", connectState);
            dataMap.put("msg", msg);
            sendData(dataMap);
        }
    };

    @Override
    public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
        LogUtil.info(TAG, "onRemoteRequest code:" + code);
        switch (code) {
            case DeviceControlConstants.ACTION_ADD_SUBSCRIBER_IDENTITY:
                String text = data.readString();
                lastIdentity = ZSONObject.stringToZSON(text).getString("identity");
                if (TextTool.isNullOrEmpty(lastIdentity)) {
                    return identityIsEmptyError(reply);
                }
                sendReply(reply, DeviceControlConstants.SUCCESS);
                return true;
            case DeviceControlConstants.ACTION_ADD_SUBSCRIBER:
                if (TextTool.isNullOrEmpty(lastIdentity)) {
                    return identityIsEmptyError(reply);
                }
                remoteObjectHandler.put(lastIdentity, data.readRemoteObject());
                lastIdentity = null;
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            case DeviceControlConstants.ACTION_REMOVE_SUBSCRIBER:
                String removeIdentity = ZSONObject.stringToZSON(data.readString()).getString("identity");
                if (TextTool.isNullOrEmpty(removeIdentity)) {
                    return identityIsEmptyError(reply);
                }
                remoteObjectHandler.remove(removeIdentity);
                sendReply(reply, DeviceControlConstants.SUCCESS);
                break;
            case DeviceControlConstants.ACTION_MESSAGE_CODE_SUBSCRIBE: // 订阅消息 1001
                remoteObjectHandler.put(DEFAULT_IDENTITY, data.readRemoteObject());
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            case DeviceControlConstants.ACTION_MESSAGE_CODE_CONNECT: // 建立连接 1008
                connectAiLifeService();
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            case DeviceControlConstants.ACTION_MESSAGE_CODE_DISCONNECT: // 断开连接 1009
                hiLinkDeviceHelper.disConnect();
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            case DeviceControlConstants.ACTION_MESSAGE_CODE_SEND_COMMAND: // 发送命令 1003
                ZSONObject zsonObj = ZSONObject.stringToZSON(data.readString());
                hiLinkDeviceHelper.sendCommand(
                    zsonObj.getString(DeviceControlConstants.MESSAGE_KEY_SERVICE_ID),
                    zsonObj.getString(DeviceControlConstants.MESSAGE_KEY_CHARACTERISTIC));
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            case DeviceControlConstants.ACTION_MESSAGE_CODE_UNSUBSCRIBE: // 取消订阅 1002
                remoteObjectHandler.remove(DEFAULT_IDENTITY);
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            case DeviceControlConstants.ACTION_MESSAGE_CODE_NOTIFY_DEVICE_ID: // 更新ID 1006
                this.deviceId = ZSONObject.stringToZSON(data.readString()).getString(DeviceControlConstants.DEVICE_ID);
                LogUtil.info(TAG, "set deviceId:" + deviceId);
                notifyPageUpdateDeviceId();
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            case DeviceControlConstants.ACTION_RE_CONFIG_NET: // 重新配网 1107
                HilinkRegister.get().openHiLinkNetConfig();
                if (!sendReply(reply, DeviceControlConstants.SUCCESS)) {
                    return false;
                }
                break;
            default:
                reply.writeString("service not defined");
                return false;
        }
        return true;
    }

    private boolean sendReply(MessageParcel reply, int replyStatus) {
        Map<String, Object> results = new HashMap<>();
        results.put(DeviceControlConstants.REPLY_CODE, replyStatus);
        return sendReply(reply, results);
    }

    private boolean sendReply(MessageParcel reply, Map<String, Object> results) {
        return reply.writeString(ZSONObject.toZSONString(results));
    }

    @Override
    public IRemoteObject asObject() {
        return this;
    }

    /**
     * 向 FA 发送数据
     *
     * @param dataMap 数据源
     */
    private void sendData(Map<String, Object> dataMap) {
        MessageParcel data = MessageParcel.obtain();
        MessageParcel reply = MessageParcel.obtain();
        MessageOption option = new MessageOption();
        data.writeString(ZSONObject.toZSONString(dataMap));
        if (remoteObjectHandler != null && !remoteObjectHandler.isEmpty()) {
            remoteObjectHandler.forEach((key, iRemoteObject) -> {
                try {
                    iRemoteObject.sendRequest(0, data, reply, option);
                } catch (RemoteException e) {
                    LogUtil.error(TAG, "failed to send data to js");
                }
            });
        }
        reply.reclaim();
        data.reclaim();
    }

    private boolean identityIsEmptyError(MessageParcel reply) {
        sendReply(reply, DataMap.newDataMap(100)
            .withCode(-1)
            .withMessage("The subscriber identity cannot be empty")
        );
        return false;
    }

    /**
     * 格式化数据源
     *
     * @param state 状态码
     * @param dataType 数据类型
     * @param result 实际数据
     * @return 格式化后数据
     */
    public Map<String, Object> formatData(String state, int dataType, String result) {
        final Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("state", state);
        dataMap.put("type", dataType);
        dataMap.put("result", result);
        return dataMap;
    }

    /**
     * 连接 hilink 服务，并订阅设备事件，获取设备信息
     */
    private void connectAiLifeService() {
        LogUtil.info(TAG, "AiLifeServiceHelper.connect start deviceId = " + deviceId);
        connectResult = AiLifeServiceHelper.connect(FAApplication.getAppContext());
        LogUtil.info(TAG, "AiLifeServiceHelper.connect result = " + connectResult + ", deviceId = " + deviceId);
        if (connectResult < ConnectResult.SERVICE_OK) {
            sendData(formatData(DeviceControlConstants.STATE_FAIL, DeviceControlConstants.AI_LIFE_SERVICE_CONNECT,
                String.valueOf(connectResult)));
        } else {
            if (hiLinkDeviceHelper == null) {
                hiLinkDeviceHelper = new HiLinkDeviceHelper(FAApplication.getAppContext(), deviceId);
                hiLinkDeviceHelper.setHiLinkDataCallback(hiLinkDataCallback);
            } else {
                hiLinkDeviceHelper.setDeviceId(deviceId);
            }
            hiLinkDeviceHelper.createConversation();
            hiLinkDeviceHelper.getHiLinkDevice();
        }
    }

    /**
     * 断开蓝牙连接
     */
    public void disconnect() {
        if (hiLinkDeviceHelper != null) {
            hiLinkDeviceHelper.disConnect();
        }
    }

    private void notifyPageUpdateDeviceId() {
        LogUtil.info(TAG, "notifyPageUpdateDeviceId deviceId = " + deviceId);
        sendData(formatData(DeviceControlConstants.STATE_SUCCESS,
            DeviceControlConstants.UPDATE_DEVICEID, this.deviceId));
    }


}
